package com.demo.dune.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.demo.dune.base.ServiceErrorException;
import com.demo.dune.dao.IOrderRepository;
import com.demo.dune.domain.MemberVO;
import com.demo.dune.domain.Order;
import com.demo.dune.domain.OrderSubmitInput;
import com.demo.dune.domain.OrderVO;
import com.demo.dune.service.strategy.MemberStrategyConst;
import com.demo.dune.service.strategy.MemberStrategyContext;
import lombok.extern.slf4j.Slf4j;

/**
 * OrderService.
 * @author Allen
 * @version 1.0 2022-04-03
 */
@Slf4j
@Service
public class OrderService {

    @Autowired
    private IOrderRepository orderRepository;
    
    @Autowired
    MemberStrategyContext memStrategyContext;
    
    @Autowired
    MemberService memberService;
    
    /**
     * findAll.
     * @return List<OrderVO>
     */
    public List<OrderVO> findAll() {
    	List<Order> orders = orderRepository.findAll();
    	List<OrderVO> orderVOs = new ArrayList<OrderVO>();
    	for (Order order : orders) {
    		OrderVO orderVO = new OrderVO(); 
    		BeanUtils.copyProperties(order, orderVO);
    		orderVOs.add(orderVO);
		}
    	BeanUtils.copyProperties(orders, orderVOs);
        return orderVOs;
    }
    
    /**
     * findByOrderCode.
     * @param orderCode
     * @return OrderVO
     */
    public OrderVO findByOrderCode(String orderCode) {
    	Order order = orderRepository.findByOrderCode(orderCode);
    	if (order == null) {
    		return null;
    	}
		OrderVO orderVO = new OrderVO(); 
		BeanUtils.copyProperties(order, orderVO);    	
        return orderVO;
    }

    /**
     * create order and update member point.If error occur, data rollback.
     * @param orderInput
     * @param member
     */
    @Transactional
    public void create(OrderSubmitInput orderInput, MemberVO member) {
    	if (orderInput == null) {
			log.error("create order error, orderInput is null");
			throw new ServiceErrorException("service error");
    	}
    	if (member == null) {
			log.error("create order error, member is null");
			throw new ServiceErrorException("service error");
    	}
    	String strategyName = MemberStrategyConst.getStrategyNameByMemType(member.getType());
    	long orderPoint = memStrategyContext.calcPoint(strategyName, orderInput.getPrice());
    	log.info("orderPoint={}", orderPoint);
    	Order order = new Order();
    	order.setOrderCode(orderInput.getOrderCode());
    	order.setMemberCode(orderInput.getMemberCode());
    	order.setItemCode(orderInput.getItemCode());
    	order.setCurrency(orderInput.getCurrency());
    	order.setPrice(orderInput.getPrice());
    	order.setCreateTime(new Date());
    	// consider whether point empty
    	long newPoint = member.getPoint() == null ? orderPoint : member.getPoint() + orderPoint;
    	member.setPoint(newPoint);
    	memberService.save(member);
    	log.info("update member point end, new point={}", member.getPoint());
    	orderRepository.save(order);
    	log.info("create order success");
    }
    
}
